{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    ""
   ]
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 举例1：大模型分析工具的调用",
   "id": "68cfb103c5edc43c"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-08T02:58:56.892433Z",
     "start_time": "2025-09-08T02:58:54.302715Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 1、获取大模型\n",
    "#导入相关依赖\n",
    "from langchain_community.tools import MoveFileTool\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langchain_core.tools import StructuredTool\n",
    "from langchain_core.utils.function_calling import convert_to_openai_function\n",
    "import os\n",
    "import dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY1\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "# 定义LLM模型\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n",
    "\n",
    "# 2、获取工具的列表\n",
    "tools = [MoveFileTool()]\n",
    "\n",
    "# 3、因为大模型invoke调用时，需要传入函数的列表，所以需要将工具转换为函数:convert_to_openai_function()\n",
    "functions = [convert_to_openai_function(t) for t in tools]\n",
    "\n",
    "# 4、获取消息列表\n",
    "messages = [HumanMessage(content=\"将文件a移动到桌面\")]\n",
    "\n",
    "# 5、调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "\n",
    "print(response)"
   ],
   "id": "a3c2e0fbcbb42003",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='' additional_kwargs={'function_call': {'arguments': '{\"source_path\":\"a\",\"destination_path\":\"/Users/YourUsername/Desktop/a\"}', 'name': 'move_file'}, 'refusal': None} response_metadata={'token_usage': {'completion_tokens': 27, 'prompt_tokens': 76, 'total_tokens': 103, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_efad92c60b', 'id': 'chatcmpl-CDMNkGJTet5BejWsNTnkE9fpJAtxv', 'service_tier': None, 'finish_reason': 'function_call', 'logprobs': None} id='run--587f6b3c-f8a6-4bde-a26e-41d67e1a5b1c-0' usage_metadata={'input_tokens': 76, 'output_tokens': 27, 'total_tokens': 103, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "作为对比：\n",
   "id": "60a63b0bcd12526"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-08T03:00:53.313858Z",
     "start_time": "2025-09-08T03:00:51.966418Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 获取消息列表\n",
    "messages = [HumanMessage(content=\"查询一下明天北京的天气\")]\n",
    "\n",
    "# 调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "\n",
    "print(response)"
   ],
   "id": "af95c5aec1112d32",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "content='抱歉，我无法提供实时天气信息。建议您查看天气预报网站或使用天气应用程序获取最新的天气信息。' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 29, 'prompt_tokens': 76, 'total_tokens': 105, 'completion_tokens_details': {'accepted_prediction_tokens': 0, 'audio_tokens': 0, 'reasoning_tokens': 0, 'rejected_prediction_tokens': 0}, 'prompt_tokens_details': {'audio_tokens': 0, 'cached_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_efad92c60b', 'id': 'chatcmpl-CDMPcUVaacw6eKtuHKMVwdKmLkZ9c', 'service_tier': None, 'finish_reason': 'stop', 'logprobs': None} id='run--ccf690d0-4b10-4808-91ff-24abfea18ceb-0' usage_metadata={'input_tokens': 76, 'output_tokens': 29, 'total_tokens': 105, 'input_token_details': {'audio': 0, 'cache_read': 0}, 'output_token_details': {'audio': 0, 'reasoning': 0}}\n"
     ]
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "通过上面两个测试发现，得到的AIMessage的核心属性如下：\n",
    "\n",
    "1、如果分析出需要调用对应的工具：\n",
    "\n",
    "content：信息为空。因为大模型要调用工具，所以就不会直接返回信息给用户\n",
    "\n",
    "additional_kwargs：包含function_call字段，指明具体函数调用的参数和函数名。比如：\n",
    "\n",
    "additional_kwargs={'function_call': {'arguments': '{\"source_path\":\"a\",\"destination_path\":\"/Users/YourUsername/Desktop/a\"}', 'name': 'move_file'}, 'refusal': None}\n",
    "\n",
    "2、如果分析出不需要调用对应的工具：\n",
    "\n",
    "content：信息不为空。\n",
    "\n",
    "additional_kwargs：不包含function_call字段\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "\n"
   ],
   "id": "af9f80c67307e468"
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": [
    "# 举例2：如何调用具体大模型分析出来的工具\n",
    "\n",
    "说明：\n",
    "\n",
    "1、大模型与Agent的核心区别：是否涉及到工具的调用\n",
    "\n",
    "2、针对于大模型：仅能分析出要调用的工具，但是此工具（或函数）不能真正的执行\n",
    "\n",
    "   针对于Agent:除了分析出要调用的工具之外，还可以执行具体的工具（或函数）"
   ],
   "id": "fa9935081b3700cb"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-08T03:47:11.419524Z",
     "start_time": "2025-09-08T03:47:10.007724Z"
    }
   },
   "cell_type": "code",
   "source": [
    "# 1、获取大模型\n",
    "#导入相关依赖\n",
    "from langchain_community.tools import MoveFileTool\n",
    "from langchain_core.messages import HumanMessage\n",
    "from langchain_core.utils.function_calling import convert_to_openai_function\n",
    "import os\n",
    "import dotenv\n",
    "from langchain_openai import ChatOpenAI\n",
    "\n",
    "dotenv.load_dotenv()\n",
    "\n",
    "os.environ['OPENAI_API_KEY'] = os.getenv(\"OPENAI_API_KEY1\")\n",
    "os.environ['OPENAI_BASE_URL'] = os.getenv(\"OPENAI_BASE_URL\")\n",
    "\n",
    "# 定义LLM模型\n",
    "chat_model = ChatOpenAI(model=\"gpt-4o-mini\", temperature=0)\n",
    "\n",
    "# 2、获取工具的列表\n",
    "tools = [MoveFileTool()]\n",
    "\n",
    "# 3、因为大模型invoke调用时，需要传入函数的列表，所以需要将工具转换为函数:convert_to_openai_function()\n",
    "functions = [convert_to_openai_function(t) for t in tools]\n",
    "\n",
    "# 4、获取消息列表\n",
    "messages = [HumanMessage(content=\"将当前目录下的文件a.txt移动到C:\\\\Users\\\\shkst\\\\Desktop\")]\n",
    "\n",
    "# 5、调用大模型（传入消息列表、工具的列表）\n",
    "response = chat_model.invoke(\n",
    "    input=messages,\n",
    "    # tools = tools, #不支持\n",
    "    functions=functions,\n",
    ")\n",
    "\n",
    "# print(response)"
   ],
   "id": "bbbfbd8b52217ad4",
   "outputs": [],
   "execution_count": 8
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "步骤1：分析下要调用哪个工具或函数",
   "id": "6347d01f2e8aca9b"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-08T03:48:13.219835Z",
     "start_time": "2025-09-08T03:48:13.209775Z"
    }
   },
   "cell_type": "code",
   "source": [
    "import json\n",
    "\n",
    "if \"function_call\" in response.additional_kwargs:\n",
    "    tool_name = response.additional_kwargs[\"function_call\"][\"name\"]\n",
    "    tool_args = json.loads(response.additional_kwargs[\"function_call\"][\"arguments\"])\n",
    "    print(f\"调用工具：{tool_name} \\n 参数：{tool_args}\")\n",
    "\n",
    "else:\n",
    "    print(f\"模型回复：{response.content}\")"
   ],
   "id": "a9841239583e055e",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "调用工具：move_file \n",
      " 参数：{'source_path': 'a.txt', 'destination_path': 'C:\\\\Users\\\\shkst\\\\Desktop\\\\a.txt'}\n"
     ]
    }
   ],
   "execution_count": 11
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "步骤2：调用对应的工具",
   "id": "124430c522dee075"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-09-08T03:48:18.337386Z",
     "start_time": "2025-09-08T03:48:18.316868Z"
    }
   },
   "cell_type": "code",
   "source": [
    "if \"move_file\" in response.additional_kwargs[\"function_call\"][\"name\"]:\n",
    "    tool = MoveFileTool()\n",
    "    result = tool.run(tool_args)  #调用工具\n",
    "    print(\"工具执行的结果\", result)"
   ],
   "id": "2b5435fff2bbffb1",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "工具执行的结果 File moved successfully from a.txt to C:\\Users\\shkst\\Desktop\\a.txt.\n"
     ]
    }
   ],
   "execution_count": 12
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
